<template>
  <div ref="filterWrap" class="filter-wrap">
    <c-form
      :options="filterOptions"
      ref="form"
      @submit="onSubmit"
      layout="inline"
      :col-span="colSpan"
      :gutter="12"
      @keyup.enter.native="handleSubmit"
      v-bind="$attrs"
      v-on="$listeners"
    >
      <template v-slot:search>
        <slot name="buttons" :submit="handleSubmit" :rest="handleReset" :toggle="handleToggleSearch">
          <div style="text-align: right;">
            <a-space style="overflow: hidden;">
              <a-button type="primary" @click="handleSubmit" icon="search" :loading="loading">查询</a-button>
              <a-button type="primary" @click="handleReset" icon="reload" :loading="loading">重置</a-button>
              <a @click="handleToggleSearch" v-if="showExpandBtn">
                {{ expanded ? '收起' : '展开' }}
                <a-icon :type="expanded ? 'up' : 'down'" />
              </a>
            </a-space>
          </div>
        </slot>
      </template>
    </c-form>
  </div>
</template>

<script>
export default {
  name: 'SearchFilter',
  props: {
    options: {
      type: Array,
      required: true
    },
    loading: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      expanded: false,
      wrapWidth: 0,
      valid: true,
      timer: 0,
      minWidth: 300,
      already: false
    }
  },
  mounted() {
    this.handleStart()
  },
  activated() {
    this.handleStart()
  },
  deactivated() {
    this.handleStop()
  },
  destroyed() {
    this.handleStop()
  },
  methods: {
    onSubmit(values) {
      this.$emit('search', values)
    },
    handleSubmit() {
      this.$refs.form.submit()
    },
    handleReset() {
      this.resetFields()
      this.$nextTick(() => {
        this.$emit('reset', this.$refs.form.initialValues)
      })
    },
    validate(...args) {
      this.$refs.form.validate(...args)
    },
    resetFields(...args) {
      this.$refs.form.resetFields(...args)
    },
    clearValidate(...args) {
      this.$refs.form.clearValidate(...args)
    },
    handleToggleSearch() {
      this.expanded = !this.expanded
    },
    onResize() {
      if (!this.valid) {
        return
      }
      this.valid = false
      const _self = this
      _self.timer = setTimeout(() => {
        _self.wrapWidth = _self.$refs.filterWrap.clientWidth
        _self.valid = true
      }, 300)
    },
    trigger(type) {
      switch (type) {
        case 'reset':
          this.handleReset()
          break
        case 'search':
          this.handleSubmit()
          break
        case 'toggle':
          this.handleToggleSearch()
        default:
          break
      }
    },
    handleStart() {
      if (this.already) return
      this.wrapWidth = this.$refs.filterWrap.clientWidth
      if (this.wrapWidth === 0) {
        this.$nextTick(() => {
          this.wrapWidth = this.$refs.filterWrap.clientWidth
        })
      }
      window.addEventListener('resize', this.onResize, false)
      this.already = true
    },
    handleStop() {
      if (!this.already) return
      this.already = false
      clearTimeout(this.timer)
      window.removeEventListener('resize', this.onResize)
    }
  },
  computed: {
    cols() {
      let cols = Math.floor(this.wrapWidth / this.minWidth)
      if (cols > 4) {
        cols = 4
      }
      if (cols < 1) {
        cols = 1
      }
      return cols
    },
    showExpandBtn() {
      return this.expandedOptions.length > this.cols
    },
    colSpan() {
      const span = 24 / this.cols
      return { span }
    },
    shrinkedOptions() {
      let array = []
      let lastSpan = this.colSpan.span
      if (this.options.length < this.cols - 1) {
        lastSpan = ((this.cols - (this.options.length % this.cols)) * 24) / this.cols
        array = [...this.options]
      } else {
        for (let i = 0; i < this.options.length; i++) {
          const item = this.options[i]
          if (!item.hidden) {
            array.push(item)
            if (array.length >= this.cols - 1) {
              break
            }
          }
        }
      }
      array.push({
        name: 'search',
        scopedSlot: 'search',
        colSpan: { span: lastSpan }
      })
      return array
    },
    allVisibleItems() {
      return this.options.filter(item => !item.hidden)
    },
    expandedOptions() {
      const lastSpan = ((this.cols - (this.allVisibleItems.length % this.cols)) * 24) / this.cols
      return [
        ...this.allVisibleItems,
        {
          name: 'search',
          scopedSlot: 'search',
          colSpan: { span: lastSpan }
        }
      ]
    },
    filterOptions() {
      if (this.expanded) {
        return this.expandedOptions
      }
      return this.shrinkedOptions
    }
  }
}
</script>

<style lang="less" scoped>
.filter-wrap {
  /deep/ .ant-col > .ant-form-item {
    height: 56px;
    margin-bottom: 0;
  }
}
</style>
